/**
 * Copyright 2008 Adam Ruggles.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package kiff.util;

import javax.persistence.Query;
import javax.persistence.TemporalType;

/**
 * Parameter Object, used as a helper object for constructing parameter queries with JPA.
 * @author Adam
 * @version $Id: Parameter.java 62 2008-10-31 04:51:50Z a.ruggles $
 * 
 * Created on Oct 23, 2008 at 12:53:00 PM 
 */
public class Parameter {
	/**
	 * Type Enumerator, used for parameters to determine what type of parameters this is.
	 * @author Adam
	 * @version $Id: Parameter.java 62 2008-10-31 04:51:50Z a.ruggles $
	 * 
	 * Created on Oct 24, 2008 at 10:20:09 AM
	 */
	public enum Type {
		/**
		 * Named Object Parameter.
		 */
		NAMED,
		/**
		 * Named Calendar Parameter.
		 */
		NAMED_CALENDAR,
		/**
		 * Named Date Parameter.
		 */
		NAMED_DATE,
		/**
		 * Position Object Parameter.
		 */
		POSITION,
		/**
		 * Position Calendar Parameter.
		 */
		POSITION_CALENDAR,
		/**
		 * Position Date Parameter.
		 */
		POSITION_DATE
	}

	/**
	 * Returns a new Parameter.
	 * @param position The position of the parameter.
	 * @param value The value of the parameter.
	 * @return A New Parameter.
	 */
	public static final Parameter create(final int position, final Object value) {
		return new Parameter(position, value);
	}

	/**
	 * Returns a new Parameter.
	 * @param position The position of the parameter.
	 * @param value The value of the parameter (java.util.Date or java.util.Calendar).
	 * @param temporalType The temporal temporalType.
	 * @return A New Parameter.
	 */
	public static final Parameter create(final int position, final Object value, final TemporalType temporalType) {
		return new Parameter(position, value, temporalType);
	}

	/**
	 * Returns a new Parameter.
	 * @param name The name of the parameter.
	 * @param value The value of the parameter.
	 * @return A New Parameter.
	 */
	public static final Parameter create(final String name, final Object value) {
		return new Parameter(name, value);
	}

	/**
	 * Returns a new Parameter.
	 * @param name The name of the parameter.
	 * @param value The value of the parameter (java.util.Date or java.util.Calendar).
	 * @param temporalType The temporal temporalType.
	 * @return A New Parameter.
	 */
	public static final Parameter create(final String name, final Object value, final TemporalType temporalType) {
		return new Parameter(name, value, temporalType);
	}

	/**
	 * The name of the parameter.
	 */
	private final String name;

	/**
	 * The position.
	 */
	private final int position;

	/**
	 * The temporal temporalType.
	 */
	private final TemporalType temporalType;

	/**
	 * The parameter type.
	 */
	private final Type type;

	/**
	 * The value of the parameter.
	 */
	private final Object value;

	/**
	 * Constructs a Parameter.
	 * @param position The position of the parameter.
	 * @param value The value of the parameter.
	 */
	public Parameter(final int position, final Object value) {
		this.position = position;
		this.name = null;
		this.value = value;
		this.temporalType = null;
		this.type = Type.POSITION;
	}

	/**
	 * Constructs a Parameter.
	 * @param position The position of the parameter.
	 * @param value The value of the parameter.
	 */
	public Parameter(final int position, final Object value, final TemporalType type) {
		this.position = position;
		this.name = null;
		this.value = value;
		this.temporalType = type;
		if (this.value instanceof java.util.Date) {
			this.type = Type.POSITION_DATE;
		} else if (this.value instanceof java.util.Calendar) {
			this.type = Type.POSITION_CALENDAR;
		} else {
			this.type = Type.POSITION;
		}
	}

	/**
	 * Constructs a Parameter.
	 * @param name The name of the parameter.
	 * @param value The value of the parameter.
	 */
	public Parameter(final String name, final Object value) {
		this.position = 0;
		this.name = name;
		this.value = value;
		this.temporalType = null;
		this.type = Type.NAMED;
	}

	/**
	 * Constructs a Parameter.
	 * @param name The name of the parameter.
	 * @param value The value of the parameter.
	 */
	public Parameter(final String name, final Object value, final TemporalType type) {
		this.position = 0;
		this.name = name;
		this.value = value;
		this.temporalType = type;
		if (this.value instanceof java.util.Date) {
			this.type = Type.NAMED_DATE;
		} else if (this.value instanceof java.util.Calendar) {
			this.type = Type.NAMED_CALENDAR;
		} else {
			this.type = Type.NAMED;
		}
	}

	/**
	 * Adds the parameter to the query.
	 * @param query The query.
	 */
	public final void addParameter(final Query query) {
		switch (type) {
		case POSITION:
			query.setParameter(position, value);
			break;
		case POSITION_CALENDAR:
			query.setParameter(position, (java.util.Calendar) value, temporalType);
			break;
		case POSITION_DATE:
			query.setParameter(position, (java.util.Date) value, temporalType);
			break;
		case NAMED:
			query.setParameter(name, value);
			break;
		case NAMED_CALENDAR:
			query.setParameter(name, (java.util.Calendar) value, temporalType);
			break;
		case NAMED_DATE:
			query.setParameter(name, (java.util.Date) value, temporalType);
			break;
		default:
			return;
		}
		
	}

	/**
	 * Returns name.
	 * @return the name.
	 */
	public String getName() {
		return name;
	}

	/**
	 * Returns position.
	 * @return the position.
	 */
	public int getPosition() {
		return position;
	}

	/**
	 * Returns temporalType.
	 * @return the temporalType.
	 */
	public TemporalType getTemporalType() {
		return temporalType;
	}

	/**
	 * Returns temporalType.
	 * @return the temporalType.
	 */
	public Type getType() {
		return type;
	}

	/**
	 * Returns value.
	 * @return the value.
	 */
	public Object getValue() {
		return value;
	}
}
